/* **************************************************
 * Archivo: AuxiliarFuncs.c                         *
 * Fecha: 05/06/2010                                *
 * Autor: Ariel Liguori                             *
 *                                                  *
 * **************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "TDAListaDestinatarios.h"
#include "TDAClienteCorreo.h"
#include "TDACorreo.h"
#include "TDACanalSeguro.h"
#include "TDAServidorInseguro.h"
#include "logdebug.h"
#include "TDA_AB.h"
#include "TDA_DNS.h"
#include "TDAPila.h"


/* Cantidad de caracteres del alfabeto. */
#define ALPHABET_QTY 26

/* Define el nombre del archivo de log por default. */
#define LOG_FILE "log.txt"

/* Maxima longitud de nombre de archivo permitida */
#define MAX_FILENAME_SIZE 32

/* Extension de los archivos de entrada */
#define DEFAULT_EXTENSION ".txt"

/* Sufijo a agregar para generar los archivos de salida */
#define DEFAULT_SUFFIX "_recv.txt"

/* Longitud del sufijo a agregar (incluye el \0) */
#define SUFFIX_LENGTH 10


/* strEnArray
   Pre.: N/A
   Post.: Devuelve true si el elemento esta en el array sino FALSE
*/
int strEnArray(char auxDest[100][100], char *destinatario, int qty){

    int i=0;

    for( ; i < qty ; i++){

        if ( !strcmp(auxDest[i], destinatario) ){
            return 1;
        }
    }

    return 0;
}

/* generarClaveRandom
   Pre.:N/A
   Post.: Se devuelve en clave un valor de clave RANDOM
*/
void generarClaveRandom(char* clave){

    size_t i=0;
    int keyLen;

    /* Seteo la semilla en un valor random */
    srand((unsigned)time(NULL));

    /* Hago que la longitud de la clave sea random entre 1 y 31 */
    keyLen = (( rand() % (MAX_KEY_LEN - 1) ) + 1);

    /* Re-Seteo la semilla en un valor random */
    srand((unsigned)time(NULL));

    for( ; i<=keyLen ; i++)
        clave[i] = ( ( rand() % ALPHABET_QTY ) + 65 );

    /* Agrego \0 al final para convertirlo en un string valido */
    clave[i] = '\0';

}

/* parser_config
   Pre.: N/A
   Post.: Se realizo un parse de la configuracion devolviendo en
          dominios los dominios validos, en clientes los clientes
          validos, en clave la clave seteada y en qtyClientes y
          qtyDominios la cantidad de clientes y dominios respect.
*/
void parser_config(char *filename,char dominios[MAX_QTY_DOMINIOS][MAX_DOMINIO_SIZE],char clientes[MAX_QTY_DEST][MAX_ADDR_SIZE],char clave[MAX_KEY_LEN], int *qtyClientes, int *qtyDominios)
{
    int i=0;
    int j=0;
    int len = 0;
    char aux[20]={0};
    FILE *archivo;

    archivo = fopen(filename,"r");

    if (archivo == NULL)
 		exit(1);

        fgets(clave,MAX_KEY_LEN,archivo);
        len = strlen(clave);
        if( clave[len-1] == '\n' )
            clave[len-1] = 0;


        fgets(aux,MAX_DOMINIO_SIZE,archivo);
        while (!feof(archivo))
        {
            while(strcmp("\n",dominios[i])!=0)
            {
            fgets(dominios[i+1],100,archivo);
            len = strlen(dominios[i+1]);
            if( (dominios[i+1][len-1] == '\n') && len != 1 )
                dominios[i+1][len-1] = 0;

            i++;
            }

        fgets(clientes[j],MAX_ADDR_SIZE,archivo);

        len = strlen(clientes[j]);
        if( clientes[j][len-1] == '\n' )
            clientes[j][len-1] = 0;

        j++;
        }

        *qtyClientes = j;
        *qtyDominios = i;

        fclose(archivo);
}


/* agregarQtyDominios
   Pre.: DNS no vacio
   Post.: Se agregaron los dominios al arbol de DNS
*/
void agregarQtyDominios(TDA_DNS *DNS, int qtyDominios, char dominios[MAX_QTY_DOMINIOS][MAX_DOMINIO_SIZE]){
    int j;

    for ( j=1 ; j < qtyDominios ; j++){
        agregarDominio (DNS, dominios[j]);
    }
}



/* enlazarServerDestConDominio
   Pre.: DNS NO Vacio
   Post.: Se enlazo cada dominio con su respectivo server (pos mem)
*/
int enlazarServerDestConDominio(TDA_DNS *DNS, TDAServidorInseguro **server,char destinatario[MAX_ADDR_SIZE]){

    char dominio[MAX_DOMINIO_SIZE];

    extraerDominio(destinatario,dominio);
    *server = obtenerValor(DNS,dominio,server);

    if ( (int)*server == 1 )
        return EXIT_FAILURE;

    return EXIT_SUCCESS;
}

/* generaClientesCorreo
   Pre.: DNS NO Vacio
   Post.: Se generaron todos los clientes de correo
        devuelve 1 en caso de error o 0 en success.
*/
int generaClientesCorreo(TDA_DNS *DNS, TDAClienteCorreo *clientesCorreo, char clientes[50][100], int qtyClientes, TDACanalSeguro *canalSeguro){

    int j;
    char dominio[MAX_DOMINIO_SIZE]={0};
    TDAServidorInseguro *server=NULL;

    for ( j=0 ; j < qtyClientes ; j++){

        crearClienteCorreo(&(clientesCorreo[j]),clientes[j]);
        obtenerClave(&(clientesCorreo[j]), *canalSeguro);
        extraerDominio(clientes[j],dominio);
        server = queryDNS(DNS,dominio,server);

        if ( (int)server == 1 )
            return EXIT_FAILURE;

        if ( conectar(&(clientesCorreo[j]), server) ){
            logmacro("\n%s\n","No fue posible conectar el cliente al servidor");
            return EXIT_FAILURE;
        }
    }

    return EXIT_SUCCESS;
}

/* enviarCorreos
   Pre.: emisor NO vacio
   Post.: Se enviaron los correos a los servers correspondientes.
*/
int enviarCorreos(int argc, char **argv, TDAClienteCorreo *emisor){

    TDACorreo correoAux;
    FILE *archivoIn;
    int i;

    for ( i=0 ; i < argc ; i++){

        if ( argc > 1 ){

            if( !i )
                i=2;
            logmacro("\n Abriendo archivo: %s\n\n",argv[i]);
            archivoIn=fopen(argv[i],"r");

            /* Chequeo que el archivo se haya abierto correctamente */
            if ( archivoIn == NULL ){
                logmacro("\nError al abrir archivo: %s\n",argv[i]);
                fclose(archivoIn);
                return EXIT_FAILURE;
            }

            if ( importarDesde(&correoAux, archivoIn) ){
                logmacro("\nError al importar correo: %s\n",argv[i]);
                fclose(archivoIn);
                return EXIT_FAILURE;
            }
            setFilename(&correoAux,argv[i]);

            if ( enviarCorreo(emisor, correoAux) ){
                logmacro("\n%s\n","Error al enviar correo.");
                fclose(archivoIn);
                return EXIT_FAILURE;
            }

            fclose(archivoIn);

        }
    }

    return EXIT_SUCCESS;
}


/* getTodosCorreosDestinatario
   Pre.: clientesCorreo NO Vacio
   Post.: Se obtuvieron los correos de todos los clientes apuntados por clientesCorreo
*/
int getTodosCorreosDestinatario(TDAClienteCorreo *clientesCorreo, int qtyClientes){

    TDACorreo correoRecibido;
    int j, qtyEmails, i;
    char destinatario[MAX_ADDR_SIZE] = {0};
    char outFilename[MAX_FILENAME] = {0};
    char auxFilename[MAX_FILENAME] = {0};
    FILE *archivoOut;
    TListaCorreo lc;


    /* Creo una variable para contener el correo recibido */
    crearCorreo(&correoRecibido);


    for ( j = 0; j < (qtyClientes-1) ; j++) {

        qtyEmails = obtenerTodos(clientesCorreo[j],&lc);

        if ( !qtyEmails ){
            getDirecUsr(clientesCorreo[j],destinatario);
            logmacro("\nNo hay emails recibidos para la cuenta '%s'\n",destinatario );
            continue;
            /*return EXIT_FAILURE;*/
        }

        LC_MoverCorriente(&lc, LO_PRIMERO);

        for( i=0; i < qtyEmails ; i++){

            LC_ObtenerCorriente(lc, &correoRecibido);
            LC_MoverCorriente(&lc, LO_SIGUIENTE);

            getFilename(correoRecibido,outFilename);

            /* Defino el nombre del archivo a grabar segun lo especificado en el TP. */
            strcpy(auxFilename,"_");
            strcat(auxFilename,clientesCorreo[j].direccion);
            strcat(auxFilename,".txt");
            memcpy(outFilename+strlen(outFilename)-strlen(DEFAULT_EXTENSION),auxFilename,(strlen(auxFilename)+1));

            /* Guardo el correo en un archivo */
            logmacro("\n Guardando mensaje en el archivo: %s\n\n",outFilename);
            archivoOut=fopen(outFilename,"w");

            /* Chequeo que el archivo se haya abierto correctamente */
            if ( archivoOut == NULL ){
                logmacro("\n%s\n","Error al abrir/crear el archivo de salida.");
                fclose(archivoOut);
                return EXIT_FAILURE;
            }

            if ( escribirA(correoRecibido, archivoOut) ){
                logmacro("\nError al escribir el correo en el archivo: %s",outFilename);
                fclose(archivoOut);
                return EXIT_FAILURE;
            }

        }

        LC_Vaciar(&lc);
    }

    return EXIT_SUCCESS;
}


/*  escribirLogServers
    Pre.: N/A
    Post.: Se guardo un archivo de log por cada server.
*/
void escribirLogServers(TDA_DNS DNS, char dominios[MAX_QTY_DOMINIOS][MAX_DOMINIO_SIZE], int qtyDominios){

    TDAServidorInseguro *server=NULL;
    int j;
    char auxFilename[MAX_FILENAME]={0};
    FILE *archivoLog;

    for ( j=1 ; j < qtyDominios ; j++){

        server = obtenerValor(&DNS,dominios[j],server);
        strcpy(auxFilename,dominios[j]);
        strcat(auxFilename,".log");

        archivoLog=fopen(auxFilename,"w");
        escribirLog(*server,archivoLog);
        fclose(archivoLog);
    }



}


/*  escribirLogServerDNS
    Pre.: N/A
    Post.: Se guardo un archivo de log con las consultas al DNS.
*/
void esribirLogServerDNS(TDA_DNS DNS){

    FILE *archivo;

    archivo=fopen("dns.log","w");
    escribirLogDNS(DNS,archivo);
    fclose(archivo);
}

